#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>
namespace RingQueue
{
    static int size_default = 5; // 队列默认大小
    template <class T>
    class ringqueue
    {
    public:
        ringqueue(int sz = size_default) : _sz(sz), _psub(0), _csub(0), _q(sz)
        {
            pthread_mutex_init(&_pmutex, nullptr);
            pthread_mutex_init(&_cmutex, nullptr);
            sem_init(&_empty, 0, _sz);
            sem_init(&_full, 0, 0);
        }
        ~ringqueue()
        {
            pthread_mutex_destroy(&_pmutex);
            pthread_mutex_destroy(&_cmutex);
            sem_destroy(&_full);
            sem_destroy(&_empty);
        }
        void Produce(const T &data)
        {
            sem_wait(&_empty);
            pthread_mutex_lock(&_pmutex);
            // 生产数据
            _q[_psub++] = data;
            _psub %= _sz;
            pthread_mutex_unlock(&_pmutex);
            sem_post(&_full);
        }
        void Consume(T &data)
        {
            sem_wait(&_full);
            pthread_mutex_lock(&_cmutex);
            // 消费数据
            data = _q[_csub++];
            _csub %= _sz;
            pthread_mutex_unlock(&_cmutex);
            sem_post(&_empty);
        }

    private:
        std::vector<T> _q;
        int _sz;                 // 环形队列大小
        int _psub;               // 生产下标
        int _csub;               // 消费下标
        pthread_mutex_t _pmutex; // 生产者互斥量
        pthread_mutex_t _cmutex; // 消费者互斥量
        sem_t _empty;            // 生产者信号量 --- 空位置
        sem_t _full;             // 消费者信号量 --- 满位置
    };
}

// #include <iostream>
// #include <vector>
// #include "sem.hpp"
// #include "mutex.hpp"
// using namespace mymutex;
// using namespace mysem;

// namespace RingQueue
// {
//     static int CAP_VAL = 5;
//     template <class T>
//     class ringqueue
//     {
//     public:
//         ringqueue(int cap = CAP_VAL) : _full_sem(0), _empty_sem(cap), _p_sub(0), _c_sub(0), _cap(cap), _q(10)
//         {
//             // pthread_mutex_init(&_pmutex, nullptr);
//             // pthread_mutex_init(&_cmutex, nullptr);
//         }
//         /*void Produce(const T &data)
//         {
//             // 判断是否存在空位置
//             _empty_sem.P(); // 申请_empty_sem信号量
//             // std::cout << "P(empty)" << std::endl;
//             // 生产数据
//             _q[_p_sub] = data;
//             _p_sub++;
//             _p_sub %= _cap;
//             // 生产了一个数据，释放_full_sem
//             _full_sem.V();
//             // std::cout << "V(full)" << std::endl;
//         }
//         void Consume(T *data)
//         {
//             // 判断是否存在数据
//             _full_sem.P(); // 申请_full_sem信号量
//             // 消费数据
//             *data = _q[_c_sub];
//             _c_sub++;
//             _c_sub %= _cap;
//             // 消费了一个数据，多了一个空位置，释放_empty_sem
//             _empty_sem.V();
//         }*/

//         // 多生产者，多消费者
//         void Produce(const T &data)
//         {
//             _empty_sem.P(); // P(empty)
//             _pmutex.Lock(); // lock(pmutex)
//             // pthread_mutex_lock(&_pmutex);

//             _q[_p_sub] = data;
//             _p_sub++;
//             _p_sub %= _cap;

//             _full_sem.V();    // V(full)
//             _pmutex.Unlock(); // unlock(pmutex)
//             // pthread_mutex_unlock(&_pmutex);
//         }
//         void Consume(T *data)
//         {
//             _full_sem.P();  // P(full)
//             _cmutex.Lock(); // lock(cmutex)
//             // pthread_mutex_lock(&_cmutex);

//             *data = _q[_c_sub];
//             _c_sub++;
//             _c_sub %= _cap;

//             _empty_sem.V();   // V(full)
//             _cmutex.Unlock(); // unlcok(cmutex)
//             // pthread_mutex_unlock(&_cmutex);
//         }

//     private:
//         sem _full_sem;  // 信号量-生产者
//         sem _empty_sem; // 信号量-消费者
//         int _p_sub;     // 生产位置
//         int _c_sub;     // 消费位置
//         int _cap;       // 环形队列大小
//         mutex _pmutex;  // 生产者锁
//         mutex _cmutex;  // 消费者锁
//         // pthread_mutex_t _pmutex;
//         // pthread_mutex_t _cmutex;

//         std::vector<T> _q;
//     };
// }
